From 235837ad4932e60f46db97934be1dfb5200e185e Mon Sep 17 00:00:00 2001 From: Carlos Soriano Date: Wed, 3 Dec 2014 15:53:59 +0100 Subject: [PATCH] gtkwindow: Use actions from focused widget to activate accel Currently we only take into account the window GActionGroup for activating the accels. However, the application could have some custom GActionGroup in the chain of focused widgets that could want to activate some action if some accel is activated while that widget is focused. To allow applications to set accels on widgets that use custom GActionGroups, simply use the muxer of the focused widget, which already contains the actions of the parents. https://bugzilla.gnome.org/show_bug.cgi?id=740682 --- gtk/gtkactionhelper.c | 2 +- gtk/gtkmenusectionbox.c | 2 +- gtk/gtkmenushell.c | 2 +- gtk/gtkwidget.c | 59 ++++++++++++++++++++++++----------------- gtk/gtkwidgetprivate.h | 3 ++- gtk/gtkwindow.c | 7 ++++- 6 files changed, 45 insertions(+), 30 deletions(-) diff --git a/gtk/gtkactionhelper.c b/gtk/gtkactionhelper.c index a9276d5b33..50060ee092 100644 --- a/gtk/gtkactionhelper.c +++ b/gtk/gtkactionhelper.c @@ -397,7 +397,7 @@ gtk_action_helper_new (GtkActionable *widget) g_object_get (G_OBJECT (helper->widget), "active", &helper->active, NULL); } - helper->action_context = _gtk_widget_get_action_muxer (GTK_WIDGET (widget)); + helper->action_context = _gtk_widget_get_action_muxer (GTK_WIDGET (widget), TRUE); return helper; } diff --git a/gtk/gtkmenusectionbox.c b/gtk/gtkmenusectionbox.c index 9905fa737d..e6b93748eb 100644 --- a/gtk/gtkmenusectionbox.c +++ b/gtk/gtkmenusectionbox.c @@ -379,7 +379,7 @@ gtk_menu_section_box_new_toplevel (GtkStack *stack, box = g_object_new (GTK_TYPE_MENU_SECTION_BOX, "margin", 10, NULL); gtk_stack_add_named (stack, GTK_WIDGET (box), "main"); - box->tracker = gtk_menu_tracker_new (GTK_ACTION_OBSERVABLE (_gtk_widget_get_action_muxer (GTK_WIDGET (box))), + box->tracker = gtk_menu_tracker_new (GTK_ACTION_OBSERVABLE (_gtk_widget_get_action_muxer (GTK_WIDGET (box), TRUE)), model, TRUE, FALSE, action_namespace, gtk_menu_section_box_insert_func, gtk_menu_section_box_remove_func, box); diff --git a/gtk/gtkmenushell.c b/gtk/gtkmenushell.c index d1d0c7f07b..939d5f4462 100644 --- a/gtk/gtkmenushell.c +++ b/gtk/gtkmenushell.c @@ -2194,7 +2194,7 @@ gtk_menu_shell_bind_model (GtkMenuShell *menu_shell, g_return_if_fail (GTK_IS_MENU_SHELL (menu_shell)); g_return_if_fail (model == NULL || G_IS_MENU_MODEL (model)); - muxer = _gtk_widget_get_action_muxer (GTK_WIDGET (menu_shell)); + muxer = _gtk_widget_get_action_muxer (GTK_WIDGET (menu_shell), TRUE); g_clear_pointer (&menu_shell->priv->tracker, gtk_menu_tracker_free); diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c index f0f2f6aa58..50ca98bf11 100644 --- a/gtk/gtkwidget.c +++ b/gtk/gtkwidget.c @@ -16481,45 +16481,54 @@ _gtk_widget_set_style (GtkWidget *widget, widget->priv->style = style; } -void -_gtk_widget_update_parent_muxer (GtkWidget *widget) +GtkActionMuxer * +_gtk_widget_get_parent_muxer (GtkWidget *widget, + gboolean create) { - GtkActionMuxer *parent_muxer; - - if (widget->priv->muxer == NULL) - return; + GtkWidget *parent; if (GTK_IS_WINDOW (widget)) - { - parent_muxer = gtk_application_get_parent_muxer_for_window (GTK_WINDOW (widget)); - } + return gtk_application_get_parent_muxer_for_window (GTK_WINDOW (widget)); + + if (GTK_IS_MENU (widget)) + parent = gtk_menu_get_attach_widget (GTK_MENU (widget)); + else if (GTK_IS_POPOVER (widget)) + parent = gtk_popover_get_relative_to (GTK_POPOVER (widget)); else - { - GtkWidget *parent; + parent = gtk_widget_get_parent (widget); - if (GTK_IS_MENU (widget)) - parent = gtk_menu_get_attach_widget (GTK_MENU (widget)); - else if (GTK_IS_POPOVER (widget)) - parent = gtk_popover_get_relative_to (GTK_POPOVER (widget)); - else - parent = gtk_widget_get_parent (widget); + if (parent) + return _gtk_widget_get_action_muxer (parent, create); - parent_muxer = parent ? _gtk_widget_get_action_muxer (parent) : NULL; - } + return NULL; +} + +void +_gtk_widget_update_parent_muxer (GtkWidget *widget) +{ + if (widget->priv->muxer == NULL) + return; - gtk_action_muxer_set_parent (widget->priv->muxer, parent_muxer); + gtk_action_muxer_set_parent (widget->priv->muxer, + _gtk_widget_get_parent_muxer (widget, TRUE)); } GtkActionMuxer * -_gtk_widget_get_action_muxer (GtkWidget *widget) +_gtk_widget_get_action_muxer (GtkWidget *widget, + gboolean create) { - if (widget->priv->muxer == NULL) + if (widget->priv->muxer) + return widget->priv->muxer; + + if (create) { widget->priv->muxer = gtk_action_muxer_new (); _gtk_widget_update_parent_muxer (widget); - } - return widget->priv->muxer; + return widget->priv->muxer; + } + else + return _gtk_widget_get_parent_muxer (widget, FALSE); } /** @@ -16548,7 +16557,7 @@ gtk_widget_insert_action_group (GtkWidget *widget, g_return_if_fail (GTK_IS_WIDGET (widget)); g_return_if_fail (name != NULL); - muxer = _gtk_widget_get_action_muxer (widget); + muxer = _gtk_widget_get_action_muxer (widget, TRUE); if (group) gtk_action_muxer_insert (muxer, name, group); diff --git a/gtk/gtkwidgetprivate.h b/gtk/gtkwidgetprivate.h index 6eddbb45e7..6fd7a63346 100644 --- a/gtk/gtkwidgetprivate.h +++ b/gtk/gtkwidgetprivate.h @@ -151,7 +151,8 @@ void _gtk_widget_invalidate_style_context (GtkWidget *widget void _gtk_widget_style_context_invalidated (GtkWidget *widget); void _gtk_widget_update_parent_muxer (GtkWidget *widget); -GtkActionMuxer * _gtk_widget_get_action_muxer (GtkWidget *widget); +GtkActionMuxer * _gtk_widget_get_action_muxer (GtkWidget *widget, + gboolean create); gchar ** _gtk_widget_list_action_prefixes (GtkWidget *widget); GActionGroup * _gtk_widget_get_action_group (GtkWidget *widget, const gchar *prefix); diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c index 16f7e049dc..842a5ff0ac 100644 --- a/gtk/gtkwindow.c +++ b/gtk/gtkwindow.c @@ -11214,7 +11214,12 @@ gtk_window_activate_key (GtkWindow *window, if (window->priv->application) { - GtkActionMuxer *muxer = _gtk_widget_get_action_muxer (GTK_WIDGET (window)); + GtkWidget *focused_widget = gtk_window_get_focus (window); + if (focused_widget == NULL) + return FALSE; + GtkActionMuxer *muxer = _gtk_widget_get_action_muxer (focused_widget, FALSE); + if (muxer == NULL) + return FALSE; return gtk_application_activate_accel (window->priv->application, G_ACTION_GROUP (muxer), -- 2.30.2